template <typename T, typename V, INT_64 TreeWidth>
FTSS::BPlusCache<T, V, TreeWidth>::BPlusCache(CCHAR_P node_storage_name,
                       CCHAR_P node_storage_white_space_name,
                       CCHAR_P leaf_storage_name,
                       CCHAR_P leaf_storage_white_space_name) : tick(0){
	fprintf(stdout, "Opening storages for BPlusTree...\n");
 	fprintf(stdout, "\tnodes storage..."); 
        storage_nodes = new FTSS::BPlusTreeNodeStorage(node_storage_name, node_storage_white_space_name);
        fprintf(stdout, "DONE\n");
        fprintf(stdout, "\tleafs storage...");
        storage_leafs = new FTSS::BPlusTreeLeafsStorage(leaf_storage_name, leaf_storage_white_space_name);
        fprintf(stdout, "DONE\n");
        fprintf(stdout, "DONE\n");
	pCacheLeafs = new FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator> ();
	pCacheNodes = new FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator> ();
	leafsKeys = new std::list<INT_64>(CLEAR_LEAFS_CACHE_SIZE);
	nodesKeys = new std::list<INT_64>(CLEAR_NODES_CACHE_SIZE);
}


template <typename T, typename V, INT_64 TreeWidth>
void FTSS::BPlusCache<T, V, TreeWidth>::clearMemory(INT_64 id){
	if (pCacheLeafs->size() > CLEAR_LEAFS_CACHE_SIZE) {
		INT_64 keyDelete = leafsKeys->front();
		leafsKeys->pop_front();
		typename FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator>::iterator fnd= pCacheLeafs->find(keyDelete);
		delete fnd->second;
		pCacheLeafs->erase(keyDelete);
	}
	if (pCacheNodes->size() > CLEAR_NODES_CACHE_SIZE) {
		INT_64 keyDelete = nodesKeys->front();
		nodesKeys->pop_front();
		typename FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator>::iterator fnd = pCacheNodes->find(keyDelete);
		delete fnd->second;
		pCacheNodes->erase(keyDelete);
	}
}


template <typename T, typename V, INT_64 TreeWidth>
BPlusNodeType *FTSS::BPlusCache<T, V, TreeWidth>::getById(INT_64 id, bool bMemClear){
	tick++;
        BPlusNodeType *res = NULL;
        // memory clearing
        if (bMemClear){
		clearMemory(id);
	}
	if (id < 0){
		typename FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator>::iterator fnd = pCacheLeafs->find(id);
		if (fnd != pCacheLeafs->end()) {
			leafsKeys->erase(fnd->second->quePos);
			leafsKeys->push_back(id);
			std::list<INT_64>::iterator it = leafsKeys->end();
			--it;
			fnd->second->quePos = it;
			return fnd->second->pNodeType;
		}
		res = storage_leafs->GetLeafById<T, V, TreeWidth>(id);
		BPlusCacheWrapper<T, V, TreeWidth> *ins = new BPlusCacheWrapper<T, V, TreeWidth>(res);
		leafsKeys->push_back(id);
		std::list<INT_64>::iterator it = leafsKeys->end();
		--it;
		ins->quePos = it;
		pCacheLeafs->insert(FTSS::Pair<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *>(id, ins));
	} else if (id > 0) {
		typename FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator>::iterator fnd = pCacheNodes->find(id);
		if (fnd != pCacheNodes->end()) {
			nodesKeys->erase(fnd->second->quePos);
			nodesKeys->push_back(id);
			std::list<INT_64>::iterator it = nodesKeys->end();
			--it;
			fnd->second->quePos = it;
			return fnd->second->pNodeType;
		}
		res = storage_nodes->GetNodeById<T, TreeWidth>(id);
		BPlusCacheWrapper<T, V, TreeWidth> *ins = new BPlusCacheWrapper<T, V, TreeWidth>(res);
		nodesKeys->push_back(id);
		std::list<INT_64>::iterator it = nodesKeys->end();
		--it;
		ins->quePos = it;
		pCacheNodes->insert(FTSS::Pair<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *>(id, ins));
	}	
	return res;
}


template <typename T, typename V, INT_64 TreeWidth>
INT_64 FTSS::BPlusCache<T, V, TreeWidth>::dumpNodeType(BPlusNodeType *pNodeType){
	if (pNodeType == NULL){
		return 0;
	}
	if (pNodeType->is_leaf){
		INT_64 returned =  storage_leafs->DumpLeaf((BPlusLeaf<T, V, TreeWidth> *)pNodeType);
		INT_64 id = ((BPlusLeaf<T, V, TreeWidth> *)pNodeType)->id;
		typename FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator>::iterator fnd = pCacheLeafs->find(id);
		if (fnd != pCacheLeafs->end()) {
			leafsKeys->erase(fnd->second->quePos);
			leafsKeys->push_back(id);
			std::list<INT_64>::iterator it = leafsKeys->end();
			--it;
			fnd->second->quePos = it;
			return returned;
		}
		BPlusCacheWrapper<T, V, TreeWidth> *ins = new BPlusCacheWrapper<T, V, TreeWidth>(pNodeType);
		leafsKeys->push_back(id);
		std::list<INT_64>::iterator it = leafsKeys->end();
		--it;
		ins->quePos = it;
		pCacheLeafs->insert(FTSS::Pair<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *>(id, ins));
		return returned;
	} else {
	        INT_64 returned = storage_nodes->DumpNode((BPlusNode<T, TreeWidth> *)pNodeType);
		INT_64 id = ((BPlusNode<T, TreeWidth> *)pNodeType)->id;
		typename FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator>::iterator fnd = pCacheNodes->find(id);
		if (fnd != pCacheNodes->end()) {
			nodesKeys->erase(fnd->second->quePos);
			nodesKeys->push_back(id);
			std::list<INT_64>::iterator it = nodesKeys->end();
			--it;
			fnd->second->quePos = it;
			return returned;
		}
		BPlusCacheWrapper<T, V, TreeWidth> *ins = new BPlusCacheWrapper<T, V, TreeWidth>(pNodeType);
		nodesKeys->push_back(id);
		std::list<INT_64>::iterator it = nodesKeys->end();
		--it;
		ins->quePos = it;
		pCacheNodes->insert(FTSS::Pair<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *>(id, ins));
		return returned;
	}
}

template <typename T, typename V, INT_64 TreeWidth>
void FTSS::BPlusCache<T, V, TreeWidth>::deleteNodeType(BPlusNodeType *pNodeType){
	if (pNodeType == NULL){
		 return;
	}
	if (pNodeType->is_leaf){
	        storage_leafs->DeleteLeaf(pNodeType->id);
	} else {
		storage_nodes->DeleteNode(pNodeType->id);
	}
}

template <typename T, typename V, INT_64 TreeWidth>
FTSS::BPlusCache<T, V, TreeWidth>::~BPlusCache() throw() {
	for (typename FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator>::iterator it = pCacheLeafs->begin();
	     it != pCacheLeafs->end();
	     ++it){
		delete it->second;
	}
	for (typename FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator>::iterator it = pCacheNodes->begin();
	     it != pCacheNodes->end();
	     ++it){
		delete it->second;
	}
	 
	delete storage_nodes;	
        delete storage_leafs;
        delete pCacheNodes;
        delete pCacheLeafs;
	delete leafsKeys;
	delete nodesKeys;
}

template <typename T, typename V, INT_64 TreeWidth>
void FTSS::BPlusCache<T, V, TreeWidth>::dumpRootId(INT_64 root){
	storage_nodes->DumpRootId(root);
}

template <typename T, typename V, INT_64 TreeWidth>
INT_64  FTSS::BPlusCache<T, V, TreeWidth>::restoreRootId(){
	return storage_nodes->RestoreRootId();
}

template <typename T, typename V, INT_64 TreeWidth>
void  FTSS::BPlusCache<T, V, TreeWidth>::dumpTreeSize(INT_64 TreeSize){
	storage_nodes->DumpTreeSize(TreeSize);
}

template <typename T, typename V, INT_64 TreeWidth>
INT_64  FTSS::BPlusCache<T, V, TreeWidth>::restoreTreeSize(){
	return storage_nodes->RestoreTreeWidth();
}

template <typename T, typename V, INT_64 TreeWidth>
void  FTSS::BPlusCache<T, V, TreeWidth>::dumpTreeWidth(INT_64 iTreeWidth){
	storage_nodes->DumpTreeWidth(iTreeWidth);
}

template <typename T, typename V, INT_64 TreeWidth>
INT_64  FTSS::BPlusCache<T, V, TreeWidth>::restoreTreeWidth(){
	return storage_nodes->RestoreTreeWidth();
}


